﻿using ShardingCore.Core.VirtualRoutes;

namespace ApplicationFrame.EntityFrameworkCore.Core
{
    /// <summary>
    /// 范围分表策略（按分表键区间分表）
    /// </summary>
    public class RangeShardingStrategy<TEntity, TKey> : AbstractShardingStrategy<TEntity, TKey> where TEntity : class
    {
        private readonly long _rangeSize;

        public RangeShardingStrategy(string shardingPropertyName, long rangeSize)
        {
            _rangeSize = rangeSize;
            ShardingPropertyName = shardingPropertyName;
        }

        public override Func<string, bool> GetRouteToFilter(TKey shardingKey, ShardingOperatorEnum shardingOperator)
        {
            var t = GetTail(shardingKey);
            switch (shardingOperator)
            {
                case ShardingOperatorEnum.GreaterThan:
                case ShardingOperatorEnum.GreaterThanOrEqual:
                    return (string tail) => long.Parse(tail) >= long.Parse(t);
                case ShardingOperatorEnum.LessThan:
                case ShardingOperatorEnum.LessThanOrEqual:
                    return (string tail) => long.Parse(tail) <= long.Parse(t);
                case ShardingOperatorEnum.Equal:
                    return (string tail) => tail == t;
                default:
                    Console.WriteLine($"shardingKey: {shardingKey}, rangeSize: {_rangeSize}, shardingOperator: {shardingOperator} is not equal scan all table tail");
                    return (string tail) => tail == t;
            }
        }

        public override string GetTail(TKey shardingKey)
        {
            if (shardingKey is ulong || shardingKey is long || shardingKey is int || shardingKey is uint)
            {
                // 计算区间索引（1-10000 → 1，10001-20000 → 2，以此类推）
                var rangeIndex = (Convert.ToUInt64(shardingKey) - 1) / (ulong)_rangeSize + 1;
                return $"{rangeIndex}";
            }

            throw new ArgumentException("type must be long or int", nameof(shardingKey));
        }

        //public override List<string> GetTails()
        //{
        //    throw new NotImplementedException();
        //}
    }
}
